home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / drdobbs / 1992 / 06 / dflt12 / popdown.c < prev    next >
Text File  |  1992-03-16  |  12KB  |  367 lines

  1. /* ------------- popdown.c ----------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int SelectionWidth(struct PopDown *);
  6. static int py = -1;
  7.  
  8. /* ------------ CREATE_WINDOW Message ------------- */
  9. static int CreateWindowMsg(WINDOW wnd)
  10. {
  11.     int rtn;
  12.     ClearAttribute(wnd, HASTITLEBAR     |
  13.                         VSCROLLBAR     |
  14.                         MOVEABLE     |
  15.                         SIZEABLE     |
  16.                         HSCROLLBAR);
  17.     rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0);
  18.     SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
  19.     SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
  20.     SendMessage(NULL, SAVE_CURSOR, 0, 0);
  21.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  22.     return rtn;
  23. }
  24.  
  25. /* --------- LEFT_BUTTON Message --------- */
  26. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  27. {
  28.     int my = (int) p2 - GetTop(wnd);
  29.     if (InsideRect(p1, p2, ClientRect(wnd)))    {
  30.         if (my != py)    {
  31.             SendMessage(wnd, LB_SELECTION,
  32.                     (PARAM) wnd->wtop+my-1, TRUE);
  33.             py = my;
  34.         }
  35.     }
  36.     else if ((int)p2 == GetTop(GetParent(wnd)))
  37.         if (GetClass(GetParent(wnd)) == MENUBAR)
  38.             PostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2);
  39. }
  40.  
  41. /* -------- BUTTON_RELEASED Message -------- */
  42. static BOOL ButtonReleasedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  43. {
  44.     py = -1;
  45.     if (InsideRect((int)p1, (int)p2, ClientRect(wnd)))    {
  46.         int sel = (int)p2 - GetClientTop(wnd);
  47.         if (*TextLine(wnd, sel) != LINE)
  48.             SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  49.     }
  50.     else    {
  51.         WINDOW pwnd = GetParent(wnd);
  52.         if (GetClass(pwnd) == MENUBAR && (int)p2==GetTop(pwnd))
  53.             return FALSE;
  54.         if ((int)p1 == GetLeft(pwnd)+2)
  55.             return FALSE;
  56.         SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  57.         return TRUE;
  58.     }
  59.     return FALSE;
  60. }
  61.  
  62. /* --------- PAINT Message -------- */
  63. static void PaintMsg(WINDOW wnd)
  64. {
  65.     int wd;
  66.     unsigned char sep[80], *cp = sep;
  67.     unsigned char sel[80];
  68.     struct PopDown *ActivePopDown;
  69.     struct PopDown *pd1;
  70.  
  71.     ActivePopDown = pd1 = wnd->mnu->Selections;
  72.     wd = MenuWidth(ActivePopDown)-2;
  73.     while (wd--)
  74.         *cp++ = LINE;
  75.     *cp = '\0';
  76.     SendMessage(wnd, CLEARTEXT, 0, 0);
  77.     wnd->selection = wnd->mnu->Selection;
  78.     while (pd1->SelectionTitle != NULL)    {
  79.         if (*pd1->SelectionTitle == LINE)
  80.             SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
  81.         else    {
  82.             int len;
  83.             memset(sel, '\0', sizeof sel);
  84.             if (pd1->Attrib & INACTIVE)
  85.                 /* ------ inactive menu selection ----- */
  86.                 sprintf(sel, "%c%c%c",
  87.                     CHANGECOLOR,
  88.                     wnd->WindowColors [HILITE_COLOR] [FG]|0x80,
  89.                     wnd->WindowColors [STD_COLOR] [BG]|0x80);
  90.             strcat(sel, " ");
  91.             if (pd1->Attrib & CHECKED)
  92.                 /* ---- paint the toggle checkmark ---- */
  93.                 sel[strlen(sel)-1] = CHECKMARK;
  94.             len=CopyCommand(sel+strlen(sel),pd1->SelectionTitle,
  95.                     pd1->Attrib & INACTIVE,
  96.                     wnd->WindowColors [STD_COLOR] [BG]);
  97.             if (pd1->Accelerator)    {
  98.                 /* ---- paint accelerator key ---- */
  99.                 int i;
  100.                 int wd1 = 2+SelectionWidth(ActivePopDown) -
  101.                                     strlen(pd1->SelectionTitle);
  102.                 for (i = 0; keys[i].keylabel; i++)    {
  103.                     if (keys[i].keycode == pd1->Accelerator)   {
  104.                         while (wd1--)
  105.                             strcat(sel, " ");
  106.                         sprintf(sel+strlen(sel), "[%s]",
  107.                             keys[i].keylabel);
  108.                         break;
  109.                     }
  110.                 }
  111.             }
  112.             if (pd1->Attrib & CASCADED)    {
  113.                 /* ---- paint cascaded menu token ---- */
  114.                 if (!pd1->Accelerator)    {
  115.                     wd = MenuWidth(ActivePopDown)-len+1;
  116.                     while (wd--)
  117.                         strcat(sel, " ");
  118.                 }
  119.                 sel[strlen(sel)-1] = CASCADEPOINTER;
  120.             }
  121.             else
  122.                 strcat(sel, " ");
  123.             strcat(sel, " ");
  124.             sel[strlen(sel)-1] = RESETCOLOR;
  125.             SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
  126.         }
  127.         pd1++;
  128.     }
  129. }
  130.  
  131. /* ---------- BORDER Message ----------- */
  132. static int BorderMsg(WINDOW wnd)
  133. {
  134.     int i, rtn = TRUE;
  135.     WINDOW currFocus;
  136.     if (wnd->mnu != NULL)    {
  137.         currFocus = inFocus;
  138.         inFocus = NULL;
  139.         rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0);
  140.         inFocus = currFocus;
  141.         for (i = 0; i < ClientHeight(wnd); i++)    {
  142.             if (*TextLine(wnd, i) == LINE)    {
  143.                 wputch(wnd, LEDGE, 0, i+1);
  144.                 wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
  145.             }
  146.         }
  147.     }
  148.     return rtn;
  149. }
  150.  
  151. /* -------------- LB_CHOOSE Message -------------- */
  152. static void LBChooseMsg(WINDOW wnd, PARAM p1)
  153. {
  154.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  155.     if (ActivePopDown != NULL)    {
  156.         int *attr = &(ActivePopDown+(int)p1)->Attrib;
  157.         wnd->mnu->Selection = (int)p1;
  158.         if (!(*attr & INACTIVE))    {
  159.             if (*attr & TOGGLE)
  160.                 *attr ^= CHECKED;
  161.             PostMessage(GetParent(wnd), COMMAND,
  162.                 (ActivePopDown+(int)p1)->ActionId, p1);
  163.         }
  164.         else
  165.             beep();
  166.     }
  167. }
  168.  
  169. /* ---------- KEYBOARD Message --------- */
  170. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  171. {
  172.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  173.     if (wnd->mnu != NULL)    {
  174.         if (ActivePopDown != NULL)    {
  175.             int c = (int)p1;
  176.             int sel = 0;
  177.             int a;
  178.             struct PopDown *pd = ActivePopDown;
  179.  
  180.             if ((c & OFFSET) == 0)
  181.                 c = tolower(c);
  182.             a = AltConvert(c);
  183.  
  184.             while (pd->SelectionTitle != NULL)    {
  185.                 char *cp = strchr(pd->SelectionTitle,
  186.                                 SHORTCUTCHAR);
  187.                 int sc = tolower(*(cp+1));
  188.                 if ((cp && sc == c) ||
  189.                         (a && sc == a) ||
  190.                             pd->Accelerator == c)    {
  191.                     PostMessage(wnd, LB_SELECTION, sel, 0);
  192.                     PostMessage(wnd, LB_CHOOSE, sel, TRUE);
  193.                     return TRUE;
  194.                 }
  195.                 pd++, sel++;
  196.             }
  197.         }
  198.     }
  199.     switch ((int)p1)    {
  200.         case F1:
  201.             if (ActivePopDown == NULL)
  202.                 SendMessage(GetParent(wnd), KEYBOARD, p1, p2);
  203.             else 
  204.                 DisplayHelp(wnd,
  205.                     (ActivePopDown+wnd->selection)->help);
  206.             return TRUE;
  207.         case ESC:
  208.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  209.             return TRUE;
  210.         case FWD:
  211.         case BS:
  212.             if (GetClass(GetParent(wnd)) == MENUBAR)
  213.                 PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  214.             return TRUE;
  215.         case UP:
  216.             if (wnd->selection == 0)    {
  217.                 if (wnd->wlines == ClientHeight(wnd))    {
  218.                     PostMessage(wnd, LB_SELECTION,
  219.                                     wnd->wlines-1, FALSE);
  220.                     return TRUE;
  221.                 }
  222.             }
  223.             break;
  224.         case DN:
  225.             if (wnd->selection == wnd->wlines-1)    {
  226.                 if (wnd->wlines == ClientHeight(wnd))    {
  227.                     PostMessage(wnd, LB_SELECTION, 0, FALSE);
  228.                     return TRUE;
  229.                 }
  230.             }
  231.             break;
  232.         case HOME:
  233.         case END:
  234.         case '\r':
  235.             break;
  236.         default:
  237.             return TRUE;
  238.     }
  239.     return FALSE;
  240. }
  241.  
  242. /* ----------- CLOSE_WINDOW Message ---------- */
  243. static int CloseWindowMsg(WINDOW wnd)
  244. {
  245.     int rtn;
  246.     WINDOW pwnd = GetParent(wnd);
  247.     SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  248.     SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  249.     SendMessage(NULL, RESTORE_CURSOR, 0, 0);
  250.     rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, 0, 0);
  251.     SendMessage(pwnd, CLOSE_POPDOWN, 0, 0);
  252.     return rtn;
  253. }
  254.  
  255. /* - Window processing module for POPDOWNMENU window class - */
  256. int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  257. {
  258.     switch (msg)    {
  259.         case CREATE_WINDOW:
  260.             return CreateWindowMsg(wnd);
  261.         case LEFT_BUTTON:
  262.             LeftButtonMsg(wnd, p1, p2);
  263.             return FALSE;
  264.         case DOUBLE_CLICK:
  265.             return TRUE;
  266.         case LB_SELECTION:
  267.             if (*TextLine(wnd, (int)p1) == LINE)
  268.                 return TRUE;
  269.             wnd->mnu->Selection = (int)p1;
  270.             break;
  271.         case BUTTON_RELEASED:
  272.             if (ButtonReleasedMsg(wnd, p1, p2))
  273.                 return TRUE;
  274.             break;
  275.         case BUILD_SELECTIONS:
  276.             wnd->mnu = (void *) p1;
  277.             wnd->selection = wnd->mnu->Selection;
  278.             break;
  279.         case PAINT:
  280.             if (wnd->mnu == NULL)
  281.                 return TRUE;
  282.             PaintMsg(wnd);
  283.             break;
  284.         case BORDER:
  285.             return BorderMsg(wnd);
  286.         case LB_CHOOSE:
  287.             LBChooseMsg(wnd, p1);
  288.             return TRUE;
  289.         case KEYBOARD:
  290.             if (KeyboardMsg(wnd, p1, p2))
  291.                 return TRUE;
  292.             break;
  293.         case CLOSE_WINDOW:
  294.             return CloseWindowMsg(wnd);
  295.         default:
  296.             break;
  297.     }
  298.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  299. }
  300.  
  301. /* --------- compute menu height -------- */
  302. int MenuHeight(struct PopDown *pd)
  303. {
  304.     int ht = 0;
  305.     while (pd[ht].SelectionTitle != NULL)
  306.         ht++;
  307.     return ht+2;
  308. }
  309.  
  310. /* --------- compute menu width -------- */
  311. int MenuWidth(struct PopDown *pd)
  312. {
  313.     int wd = 0, i;
  314.     int len = 0;
  315.  
  316.     wd = SelectionWidth(pd);
  317.     while (pd->SelectionTitle != NULL)    {
  318.         if (pd->Accelerator)    {
  319.             for (i = 0; keys[i].keylabel; i++)
  320.                 if (keys[i].keycode == pd->Accelerator)    {
  321.                     len = max(len, 2+strlen(keys[i].keylabel));
  322.                     break;
  323.                 }
  324.         }
  325.         if (pd->Attrib & CASCADED)
  326.             len = max(len, 2);
  327.         pd++;
  328.     }
  329.     return wd+5+len;
  330. }
  331.  
  332. /* ---- compute the maximum selection width in a menu ---- */
  333. static int SelectionWidth(struct PopDown *pd)
  334. {
  335.     int wd = 0;
  336.     while (pd->SelectionTitle != NULL)    {
  337.         int len = strlen(pd->SelectionTitle)-1;
  338.         wd = max(wd, len);
  339.         pd++;
  340.     }
  341.     return wd;
  342. }
  343.  
  344. /* ----- copy a menu command to a display buffer ---- */
  345. int CopyCommand(unsigned char *dest, unsigned char *src,
  346.                                         int skipcolor, int bg)
  347. {
  348.     unsigned char *d = dest;
  349.     while (*src && *src != '\n')    {
  350.         if (*src == SHORTCUTCHAR)    {
  351.             src++;
  352.             if (!skipcolor)    {
  353.                 *dest++ = CHANGECOLOR;
  354.                 *dest++ = cfg.clr[POPDOWNMENU]
  355.                             [HILITE_COLOR] [BG] | 0x80;
  356.                 *dest++ = bg | 0x80;
  357.                 *dest++ = *src++;
  358.                 *dest++ = RESETCOLOR;
  359.             }
  360.         }
  361.         else
  362.             *dest++ = *src++;
  363.     }
  364.     return (int) (dest - d);
  365. }
  366.  
  367.